#include "includesT.h"
#include "pocsT.h"


using namespace std;


struct thread_data
{
	int J;
	int N;
	ScanData *S;
};

struct thread_data thread_data_array[NUM_THREADS];

void *IterateLine(void *threadarg){
	struct thread_data *data;
	data = (struct thread_data *) threadarg;
	int j = data->J;
	int n = data->N;
	ScanData *s= data->S;
	int i;
	for(i=1;i<=n;i++){
		//P3apriori(*s,j);
		P1hilbert(*s,j);
		P2compact(*s,j);
		P3apriori(*s,j);
		P4fproject(*s,j);
		P5nonneg(*s,j);
	}

	pthread_exit((void*) j);
}

void ThreadPocs(ScanData & s){
	pthread_t thread[NUM_THREADS];
	pthread_attr_t attr;
	int numit = 100;
	int rc;
	int j;
	void *status;
	/* Initialize and set thread detached attribute */
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);


	for (j=0;j<s.Ny;j++){
		if(s.Lmask[j]){
			thread_data_array[j].S = &s;
			thread_data_array[j].N = numit;
			thread_data_array[j].J = j;
			rc = pthread_create(&thread[j], &attr, IterateLine, (void *) &thread_data_array[j]);
			if (rc) {
				cout<< "ERROR; return code from pthread_create() is "<< rc <<endl;
				exit(-1);
			}
		}
	}
	pthread_attr_destroy(&attr);
	for(j=0;j<s.Ny;j++) {
		if(s.Lmask[j]){
			rc = pthread_join(thread[j], &status);
			if (rc) {
				cout<< "ERROR; return code from pthread_join() is "<< rc <<endl;
				exit(-1);
			}
		}
	}
}

int main (int argc, char* argv[]) 
{
	time_t t0, t1,t2;
	int i,j;
	bool initalguess = false;
	float x=0,y=0,a=90.*1.05,b=117.5*1.05;
	double dif;
	//double f = 54.889599/2.*348./888.;	
	//double f = 54.889599/2.*250./888.;
	int fov = 128;
	// ng , gmin , gmax , nt, tmi, tma , rad, nx, ny
	//ScanData s = ScanData(348,-f/180.*M_PI , f/180.*M_PI, 984, -M_PI_2, 3.*M_PI_2, 541, 512, 512,fov);
	//ScanData s = ScanData(250,-f/180.*M_PI , f/180.*M_PI, 984, 3.*M_PI_2, 3.*M_PI_2, 541, 512, 512,fov);
	double f = 15.4533/2.;
	ScanData s = ScanData(888,-f/180.*M_PI , f/180.*M_PI, 984, M_PI, M_PI, 541, 512, 512,fov);
	cout << "Reading data" <<endl;

	// Compact support data test
	for (i=0; i<s.Nx; i++){
		x = s.xmin + i*s.dx;
		for (j=0;j<s.Ny; j++){
			y = s.ymin + j*s.dy;
			if (x*x/a/a + y*y/b/b < 1.) s.CSmask[i][j] = true;
		}
	}
	j=0;i=0;
	//ifstream file ("../../../data/testTrunc.csv");
	ifstream file ("../../../data/dataBetterSample.csv");
	file.precision(20);
		
	string line;
	while (getline (file, line))
	{
		istringstream linestream(line);
		string item;
		while (getline (linestream, item, ','))
		{
			s.data[j][i]  = (float) atof( item.c_str() );
			j++;
		}
		j=0;
		i++;
	}
	file.close();


	i = 0; j=0;
	file.open("../../../data/APmask_512_croiss.csv",ifstream::in);
	while (getline (file, line))
	{
		istringstream linestream(line);
		string item;
		while (getline (linestream, item, ','))
		{
			s.APmask[i][j]  = (float) atoi( item.c_str() );
			j++;
		}
		j=0;
		i++;
	}
	file.close();

	i = 0; j=0;
	file.open("../../../data/APdata_512_croiss.csv",ifstream::in);
	file.precision(20);
	while (getline (file, line))
	{
		istringstream linestream(line);
		string item;
		while (getline (linestream, item, ','))
		{
			s.APdata[i][j]  = (float) atof( item.c_str() );
			j++;
		}
		j=0;
		i++;
	}
	file.close();

	if(initalguess){
		i = 0; j=0;
		file.open("testPOCS.csv",ifstream::in);
		file.precision(20);
		while (getline (file, line))
		{
			istringstream linestream(line);
			string item;
			while (getline (linestream, item, ','))
			{
				s.recon[i][j]  = (float) atof( item.c_str() );
				j++;
			}
			j=0;
			i++;
		}
		file.close();
	}
	time(&t0);
	cout << "Preparing data" << endl;
	prepare(s);
	time(&t1);
	cout << "Preparation time: "<< difftime(t1,t0)<<" sec"<<endl;
	cout << "Iterating" << endl;
	ThreadPocs(s);
	time(&t2);
	cout << "Time to iterate: "<< difftime(t2,t1)<<" sec"<<endl;
	cout<< "Writing to file" << endl;
	// write to file
	ofstream outfile ("testPOCS.csv",ios::trunc);
	outfile.precision(20);
	for(i=0;i<s.Nx;++i){

		for(j=0;j<s.Ny;++j){
			outfile << s.recon[i][j] << ",";
			//outfile << s.DBPmask[i][j] + s.CSmask[i][j] << ",";
		}
		outfile << "\n";
	}
	outfile.close();

	
	return 0;
}
